import 'package:flutter/widgets.dart';
import '../file_explorer_controller.dart';
import '../file_node.dart';
import 'file_explorer_manager.dart';

/// [ExpandedNodesEnsurer]：用于**确保文件树中已展开的节点数据加载完成**的辅助类。
///
/// 功能：
/// - 避免重复调用 `ensureExpandedNodesLoaded`（内部通过 `_isEnsuring` 和 `_ensurePosted` 控制）；
/// - 使用 [WidgetsBinding.addPostFrameCallback] 在当前帧结束后异步执行，避免在构建阶段直接触发异步任务；
/// - 在操作过程中自动处理状态标记，保证同一时间只有一次实际执行。
///
/// 使用场景：
/// - 文件树需要在渲染完成后，确保已展开节点的数据已全部加载；
/// - 防止重复触发加载，导致性能浪费或竞态问题。
///
/// 使用示例：
/// ```dart
/// final ensurer = ExpandedNodesEnsurer();
///
/// ensurer.schedule(
///   ctl: fileExplorerController,
///   roots: rootNodes,
///   manager: fileExplorerManager,
/// );
/// ```
class ExpandedNodesEnsurer {
  bool _isEnsuring = false;
  bool _ensurePosted = false;

  /// 调度一次“确保展开节点加载”的操作。
  ///
  /// - [ctl] 文件浏览器控制器（可用于持有当前状态）；
  /// - [roots] 根节点列表（需要确认展开状态的入口点）；
  /// - [manager] [FileExplorerManager]，负责实际的加载逻辑；
  ///
  /// 内部逻辑：
  /// 1. 如果已有任务在执行或已调度，则直接返回，避免重复；
  /// 2. 否则标记 `_ensurePosted = true`，并在下一帧结束后执行；
  /// 3. 执行 [manager.ensureExpandedNodesLoaded]，传入 [roots]；
  /// 4. 执行完成后清理 `_isEnsuring` 状态。
  void schedule({
    required FileExplorerController ctl,
    required List<FileNode> roots,
    required FileExplorerManager manager,
  }) {
    if (_ensurePosted || _isEnsuring) return;
    _ensurePosted = true;
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      _ensurePosted = false;
      if (_isEnsuring) return;
      _isEnsuring = true;
      try {
        await manager.ensureExpandedNodesLoaded(roots);
      } finally {
        _isEnsuring = false;
      }
    });
  }
}
